package youfu

import (
	"bytes"
	"crypto"
	"crypto/des"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"io/ioutil"

	"fmt"
)

// base64 加密
func base64Encode(data []byte) string {
	return base64.StdEncoding.EncodeToString(data)
}

// base64 解密
func base64Decode(data string) ([]byte, error) {
	return base64.StdEncoding.DecodeString(data)
}

func jsonMarshal(v interface{}) string {
	if v == nil {
		return ""
	}
	if r, err := json.Marshal(v); err != nil {
		return ""
	} else {
		return string(r)
	}
}

func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}

func PKCS5UnPadding(origData []byte) []byte {
	length := len(origData)
	// 去掉最后一个字节 unpadding 次
	unpadding := int(origData[length-1])
	return origData[:(length - unpadding)]
}

func DesECBEntrypt(data, key []byte) []byte {
    if len(key) > 0 {
        key = key[:]
    }
    block, err := des.NewCipher(key)
    if err != nil {
        fmt.Printf("EntryptDesECB newCipher error[%v]", err)
        return []byte("")
    }
    bs := block.BlockSize()
    data = PKCS5Padding(data, bs)
    if len(data)%bs != 0 {
        fmt.Printf("EntryptDesECB Need a multiple of the blocksize")
        return []byte("")
    }
    out := make([]byte, len(data))
    dst := out
    for len(data) > 0 {
        block.Encrypt(dst, data[:bs])
        data = data[bs:]
        dst = dst[bs:]
    }
    return out
}

func DESECBDecrypt(data, key []byte) (string, error) {
    if len(key) > 0 {
        key = key[:]
    }
    block, err := des.NewCipher(key)
    if err != nil {
        return "", fmt.Errorf("DecryptDES NewCipher error[%v]", err)
    }
    bs := block.BlockSize()
    if len(data)%bs != 0 {
        return "", fmt.Errorf("DecryptDES crypto/cipher: input not full blocks")
    }
    out := make([]byte, len(data))
    dst := out
    for len(data) > 0 {
        block.Decrypt(dst, data[:bs])
        data = data[bs:]
        dst = dst[bs:]
    }
    out = PKCS5UnPadding(out)
    return string(out), nil
}

func RsaSign(data []byte, priKey *rsa.PrivateKey) (string, error) {
	hash := sha256.New()
	hash.Write(data)
	sha256Res := hash.Sum(nil)

	sha256Str := fmt.Sprintf("%x", sha256Res)

	// 银联这个需要拿第一次sha256的结果进行hash, 然后第二次hash的结果进行签名
	messageBytes := bytes.NewBufferString(sha256Str)
	hash = sha256.New()
	hash.Write(messageBytes.Bytes())
	sha256Res = hash.Sum(nil)

	rng := rand.Reader
	signer, err := rsa.SignPKCS1v15(rng, priKey, crypto.SHA256, sha256Res[:])
	if err != nil {
		fmt.Printf("SignPKCS1v15 error: %s", err.Error())
		return "", err
	}
	return base64Encode(signer), nil
}

func ReadFile(file string) ([]byte, error) {
    f, err := ioutil.ReadFile(file)
    if err != nil {
        fmt.Println("read fail", err)
		return nil, err
	}
    return f, nil
}